package com.iflytek.cosmo.ocr.common.metric;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.iflytek.cosmo.ocr.common.config.MetricConfig;
import com.iflytek.cosmo.ocr.common.constant.MetricsConstant;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.micrometer.core.instrument.Timer;

/**
 * 指标统计
 * @author dgyu
 *
 */
@Component
public class OcrProcessMicrometer {

	private static final Logger	 logger	  = LoggerFactory.getLogger(OcrProcessMicrometer.class);

	private MeterRegistry		 meterRegistry;

	@Autowired
	private MetricConfig		 metricConfig;

	private Map<String, Counter> counters = new ConcurrentHashMap<>(128);

	private Map<String, Timer>	 timers	  = new ConcurrentHashMap<>(128);

	public OcrProcessMicrometer(MeterRegistry meterRegistry) {
		this.meterRegistry = meterRegistry;
	}
	
	//String clientIp, String metric, Object value, String tags, String sendType
	
	public <T> void statisticsDaPullInTotal(Map<String,String> argus) {
		Map<String, String> tagMap = new HashMap<>();
		getTagMap(argus, tagMap);
		getCounter(counters, MetricsConstant.METRICS_KEY_OCR_EXPORT_SINGLE_FILE_TOTAL, MetricsConstant.EVENT_TIME, stampToDate(), tagMap).increment();
		logger.debug("==== metric name:{} == in_count+1 ========", MetricsConstant.METRICS_KEY_OCR_EXPORT_SINGLE_FILE_TOTAL);
	}


	/**
	 * 统计处理异常量
	 * @param argus
	 * @param exceptionMessage
	 */
	public <T> void statisticsdaPullInErrorTotal(Map<String,String> argus, String exceptionMessage) {
		Map<String, String> tagMap = new HashMap<>();
		getTagMap(argus, tagMap);
		if (StringUtils.isNotBlank(exceptionMessage)) {
			tagMap.put(MetricsConstant.EXCEPTION_MESSAGE, exceptionMessage);
		}
		getCounter(counters, MetricsConstant.METRICS_KEY_DA_PULL_IN_ERROR_TOTAL, MetricsConstant.EVENT_TIME, stampToDate(), tagMap).increment();
		logger.debug("==== metric name:{} == in_count+1 ========", MetricsConstant.METRICS_KEY_DA_PULL_IN_ERROR_TOTAL);
	}
	
	private <T> void getTagMap(Map<String, String> argus, Map<String, String> tagMap) {
		if(null !=argus.get("id")) {
			//tagMap.put(MetricsConstant.METRICS_ID, argus.get("id"));
			for (Map.Entry<String, String> set : argus.entrySet()) {
				if(!"id".equals(set.getKey())) {
					tagMap.put(set.getKey(), set.getValue());
				}
			}
		}
	}

	/**
	 * 统计da处理异常量
	 * @param exceptionMessage
	 */
	public <T> void statisticsdaPullInErrorTotal(String exceptionMessage) {
		Map<String, String> tagMap = new HashMap<>();
		if (StringUtils.isNotBlank(exceptionMessage)) {
			tagMap.put(MetricsConstant.EXCEPTION_MESSAGE, exceptionMessage);
		}
		getCounter(counters, MetricsConstant.METRICS_KEY_DA_PULL_IN_ERROR_TOTAL, MetricsConstant.EVENT_TIME, stampToDate(), tagMap).increment();
		logger.debug("==== metric name:{} == in_count+1 ========", MetricsConstant.METRICS_KEY_DA_PULL_IN_ERROR_TOTAL);
	}


	private String stampToDate() {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
		Date date = new Date(System.currentTimeMillis());
		return simpleDateFormat.format(date);
	}

	/**
	 */
	private Counter getCounter(Map<String, Counter> counterMap, String name, String tagName, String date, Map<String, String> tagMap) {
		StringBuffer sb = new StringBuffer(name);
		if (null != tagMap) {
			for (Map.Entry<String, String> set : tagMap.entrySet()) {
				sb.append("_").append(set.getValue());
			}
		}
		String key = String.format("%s_%s", sb.toString(), date);
		if (!counterMap.containsKey(key)) {
			synchronized (counterMap) {
				if (!counterMap.containsKey(key)) {
					Counter.Builder builder = Counter.builder(name);
					if (metricConfig.getTagEnabled() && StringUtils.isNotEmpty(date)) {
						builder.tag(tagName, date);
					}
					if (null != tagMap) {
						for (Map.Entry<String, String> set : tagMap.entrySet()) {
							builder.tag(set.getKey(), set.getValue());
						}
					}
					counterMap.put(key, builder.register(meterRegistry));
				}
			}
		}
		return counterMap.get(key);
	}

	/**
	 * 统计各个节点耗时时间
	 * <br>
	 * 适用场景:	<br>
	 * 调用方式:	<br>
	 * 业务逻辑说明<br>
	 *
	 * @param key
	 * @param message
	 * @param begin
	 * @param end
	 * @autho dgyu
	 * @time 2019年7月5日 上午10:21:45
	 */
	public <T> void metricProcessCostTime(String key, Map<String,String> argus, long begin, long end) {
		if (null == argus || null == argus.get("id")) {
			return;
		}
		getTimer(timers, key + MetricsConstant.COST_TIME, argus).record(end - begin, TimeUnit.MILLISECONDS);
		logger.debug("==== metric name:{} == cost_time_count+1 ========", key + MetricsConstant.COST_TIME+ "_seconds_max");
	}

	private Timer getTimer(Map<String, Timer> timerMap, String name, Map<String, String> tagMap) {
		StringBuffer sb = new StringBuffer(name);
		if (null != tagMap) {
			for (Map.Entry<String, String> set : tagMap.entrySet()) {
				sb.append("_").append(set.getValue());
			}
		}
		String key = sb.toString();
		if (!timerMap.containsKey(key)) {
			synchronized (timerMap) {
				if (!timerMap.containsKey(key)) {
					Timer.Builder builder = Timer.builder(name);
					if (null != tagMap) {
						for (Map.Entry<String, String> set : tagMap.entrySet()) {
							builder.tag(set.getKey(), set.getValue());
						}
					}
					timerMap.put(key, builder.register(meterRegistry));
				}
			}
		}
		return timerMap.get(key);
	}

}